package com.icesoft.xsnow.common.security.util;

import cn.hutool.core.util.StrUtil;
import com.icesoft.xsnow.common.core.constant.SecurityConstants;
import com.icesoft.xsnow.common.security.dto.XSnowUser;
import lombok.experimental.UtilityClass;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;

/**
 * @program: xsnow
 * @description: 安全工作类
 * @author: xuefeng.gao
 * @create: 2019-05-13 16:20
 **/
@UtilityClass       //工具类注解
public class SecurityUtils {

    private static XSnowUser anonymous;

    /**
     * 获取Authentication
     */
    public Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }

    /**
     * 获取用户
     *
     * @param authentication
     * @return PigxUser
     * <p>
     * 获取当前用户的全部信息 EnablePigxResourceServer true
     * 获取当前用户的用户名 EnablePigxResourceServer false
     */
    public XSnowUser getUser(Authentication authentication) {
        Object principal = Optional.ofNullable(authentication)
                .map(auth -> auth.getPrincipal() ).orElse(anonymous());
        if (principal instanceof XSnowUser) {
            return (XSnowUser) principal;
        } else if(principal instanceof String && StrUtil.equals("anonymousUser",(String)principal)){
            return anonymous();
        }
        return null;
    }

    /**
     * 获取用户
     */
    public XSnowUser getUser() {
        Authentication authentication = getAuthentication();
        return getUser(authentication);
    }

    /**
     * 获取用户角色信息
     *
     * @return 角色集合
     */
    public List<Integer> getRoles() {
        Authentication authentication = getAuthentication();
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();

        List<Integer> roleIds = new ArrayList<>();
        authorities.stream()
                .filter(granted -> StrUtil.startWith(granted.getAuthority(), SecurityConstants.ROLE))
                .forEach(granted -> {
                    String id = StrUtil.removePrefix(granted.getAuthority(), SecurityConstants.ROLE);
                    roleIds.add(Integer.parseInt(id));
                });
        return roleIds;
    }

    private final static XSnowUser anonymous(){
         return  Optional.ofNullable(anonymous)
                 .orElseGet(()-> {
                             Collection<? extends GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ANONYMOUS");
                             anonymous = new XSnowUser(0, SecurityConstants.USER_ANONYMOUS, SecurityConstants.N_A,
                                     null, null, null, authorities);
                             return anonymous;
                         });
    }


}
